import 'dart:async';  
  
import 'package:chewie/src/chewie_player.dart';  
import 'package:chewie/src/chewie_progress_colors.dart';  
import 'package:chewie/src/material_progress_bar.dart';  
import 'package:chewie/src/utils.dart';  
import 'package:flutter/material.dart';  
import 'package:video_player/video_player.dart';  
  
///自定义播放器UI  
class MaterialControls extends StatefulWidget {  
  //初始化时是否展示loading  
  final bool showLoadingOnInitialize;  
  
  //是否展示大播放按钮  
  final bool showBigPlayIcon;  
  
  //视频浮层  
  final Widget overlayUI;  
  
  //底部渐变  
  final Gradient bottomGradient;  
  
  //弹幕浮层  
  final Widget barrageUI;  
  
  const MaterialControls(  
      {Key key,  
        this.showLoadingOnInitialize = true,  
        this.showBigPlayIcon = true,  
        this.overlayUI,  
        this.bottomGradient,  
        this.barrageUI})  
      : super(key: key);  
  
  @override  
  State<StatefulWidget> createState() {  
    return _MaterialControlsState();  
  }  
}  
  
class _MaterialControlsState extends State<MaterialControls>  
    with SingleTickerProviderStateMixin {  
  VideoPlayerValue _latestValue;  
  double _latestVolume;  
  bool _hideStuff = true;  
  Timer _hideTimer;  
  Timer _initTimer;  
  Timer _showAfterExpandCollapseTimer;  
  bool _dragging = false;  
  bool _displayTapped = false;  
  
  final barHeight = 48.0;  
  final marginSize = 5.0;  
  
  VideoPlayerController controller;  
  ChewieController chewieController;  
  AnimationController playPauseIconAnimationController;  
  
  @override  
  Widget build(BuildContext context) {  
    if (_latestValue.hasError) {  
      return chewieController.errorBuilder != null  
          ? chewieController.errorBuilder(  
        context,  
        chewieController.videoPlayerController.value.errorDescription,  
      )  
          : const Center(  
        child: Icon(  
          Icons.error,  
          color: Colors.white,  
          size: 42,  
        ),  
      );  
    }  
  
    return MouseRegion(  
      onHover: (_) {  
        _cancelAndRestartTimer();  
      },  
      child: GestureDetector(  
        onTap: () => _cancelAndRestartTimer(),  
        child: AbsorbPointer(  
          absorbing: _hideStuff,  
          child: Stack(  
            children: [  
              widget.barrageUI ?? Container(),  
              Column(  
                children: <Widget>[  
                  if (_latestValue != null &&  
                      !_latestValue.isPlaying &&  
                      _latestValue.duration == null ||  
                      _latestValue.isBuffering)  
                    Expanded(  
                      child: Center(  
                        child: _loadingIndicator(),  
                      ),  
                    )  
                  else  
                    _buildHitArea(),  
                  _buildBottomBar(context),  
                ],  
              ),  
              _overlayUI()  
            ],  
          ),  
        ),  
      ),  
    );  
  }  
  
  @override  
  void dispose() {  
    _dispose();  
    super.dispose();  
  }  
  
  void _dispose() {  
    controller.removeListener(_updateState);  
    _hideTimer?.cancel();  
    _initTimer?.cancel();  
    _showAfterExpandCollapseTimer?.cancel();  
  }  
  
  @override  
  void didChangeDependencies() {  
    final _oldController = chewieController;  
    chewieController = ChewieController.of(context);  
    controller = chewieController.videoPlayerController;  
  
    playPauseIconAnimationController ??= AnimationController(  
      vsync: this,  
      duration: const Duration(milliseconds: 400),  
      reverseDuration: const Duration(milliseconds: 400),  
    );  
  
    if (_oldController != chewieController) {  
      _dispose();  
      _initialize();  
    }  
  
    super.didChangeDependencies();  
  }  
  
  ///底部控制栏  
  AnimatedOpacity _buildBottomBar(  
      BuildContext context,  
      ) {  
    final iconColor = Theme.of(context).textTheme.button.color;  
  
    return AnimatedOpacity(  
      opacity: _hideStuff ? 0.0 : 1.0,  
      duration: const Duration(milliseconds: 300),  
      child: Container(  
        height: barHeight,  
        decoration: BoxDecoration(  
          //渐变  
            gradient: widget.bottomGradient),  
        child: Row(  
          children: <Widget>[  
            _buildPlayPause(controller),  
            if (chewieController.isLive)  
              const SizedBox()  
            else  
              _buildProgressBar(),  
            if (chewieController.isLive)  
              const Expanded(child: Text('LIVE'))  
            else  
              _buildPosition(iconColor),  
            if (chewieController.allowPlaybackSpeedChanging)  
              _buildSpeedButton(controller),  
            if (chewieController.allowMuting) _buildMuteButton(controller),  
            if (chewieController.allowFullScreen) _buildExpandButton(),  
          ],  
        ),  
      ),  
    );  
  }  
  
  ///展开按钮  
  GestureDetector _buildExpandButton() {  
    return GestureDetector(  
      onTap: _onExpandCollapse,  
      child: AnimatedOpacity(  
        opacity: _hideStuff ? 0.0 : 1.0,  
        duration: const Duration(milliseconds: 300),  
        child: Container(  
          height: barHeight,  
          padding: const EdgeInsets.only(  
            left: 8.0,  
            right: 8.0,  
          ),  
          child: Center(  
            child: Icon(  
              chewieController.isFullScreen  
                  ? Icons.fullscreen_exit_rounded  
                  : Icons.fullscreen_rounded,  
              color: Colors.white,  
            ),  
          ),  
        ),  
      ),  
    );  
  }  
  
  Expanded _buildHitArea() {  
    final bool isFinished = _latestValue.position >= _latestValue.duration;  
  
    return Expanded(  
      child: GestureDetector(  
        onTap: () {  
          if (_latestValue != null && _latestValue.isPlaying) {  
            if (_displayTapped) {  
              setState(() {  
                _hideStuff = true;  
              });  
            } else {  
              _cancelAndRestartTimer();  
            }  
          } else {  
            _playPause();  
  
            setState(() {  
              _hideStuff = true;  
            });  
          }  
        },  
        child: Container(  
          color: Colors.transparent,  
          child: Center(  
            child: AnimatedOpacity(  
              opacity:  
              _latestValue != null && !_latestValue.isPlaying && !_dragging  
                  ? 1.0  
                  : 0.0,  
  
              ///中间播放按钮  
              duration: const Duration(milliseconds: 300),  
              child: widget.showBigPlayIcon  
                  ? GestureDetector(  
                child: Container(  
                  decoration: BoxDecoration(  
                    color: Theme.of(context).dialogBackgroundColor,  
                    borderRadius: BorderRadius.circular(48.0),  
                  ),  
                  child: Padding(  
                    padding: const EdgeInsets.all(12.0),  
                    child: IconButton(  
                        icon: isFinished  
                            ? const Icon(Icons.replay, size: 32.0)  
                            : AnimatedIcon(  
                          icon: AnimatedIcons.play_pause,  
                          progress:  
                          playPauseIconAnimationController,  
                          size: 32.0,  
                        ),  
                        onPressed: () {  
                          _playPause();  
                        }),  
                  ),  
                ),  
              )  
                  : Container(),  
            ),  
          ),  
        ),  
      ),  
    );  
  }  
  
  Widget _buildSpeedButton(  
      VideoPlayerController controller,  
      ) {  
    return GestureDetector(  
      onTap: () async {  
        _hideTimer?.cancel();  
  
        final chosenSpeed = await showModalBottomSheet<double>(  
          context: context,  
          isScrollControlled: true,  
          useRootNavigator: true,  
          builder: (context) => _PlaybackSpeedDialog(  
            speeds: chewieController.playbackSpeeds,  
            selected: _latestValue.playbackSpeed,  
          ),  
        );  
  
        if (chosenSpeed != null) {  
          controller.setPlaybackSpeed(chosenSpeed);  
        }  
  
        if (_latestValue.isPlaying) {  
          _startHideTimer();  
        }  
      },  
      child: AnimatedOpacity(  
        opacity: _hideStuff ? 0.0 : 1.0,  
        duration: const Duration(milliseconds: 300),  
        child: ClipRect(  
          child: Container(  
            height: barHeight,  
            padding: const EdgeInsets.only(  
              left: 8.0,  
              right: 8.0,  
            ),  
            child: const Icon(Icons.speed),  
          ),  
        ),  
      ),  
    );  
  }  
  
  GestureDetector _buildMuteButton(  
      VideoPlayerController controller,  
      ) {  
    return GestureDetector(  
      onTap: () {  
        _cancelAndRestartTimer();  
  
        if (_latestValue.volume == 0) {  
          controller.setVolume(_latestVolume ?? 0.5);  
        } else {  
          _latestVolume = controller.value.volume;  
          controller.setVolume(0.0);  
        }  
      },  
      child: AnimatedOpacity(  
        opacity: _hideStuff ? 0.0 : 1.0,  
        duration: const Duration(milliseconds: 300),  
        child: ClipRect(  
          child: Container(  
            height: barHeight,  
            padding: const EdgeInsets.only(  
              left: 8.0,  
              right: 8.0,  
            ),  
            child: Icon(  
              (_latestValue != null && _latestValue.volume > 0)  
                  ? Icons.volume_up  
                  : Icons.volume_off,  
            ),  
          ),  
        ),  
      ),  
    );  
  }  
  
  ///暂停和播放icon  
  GestureDetector _buildPlayPause(VideoPlayerController controller) {  
    return GestureDetector(  
      onTap: _playPause,  
      child: Container(  
        height: barHeight,  
        color: Colors.transparent,  
        padding: const EdgeInsets.only(  
          left: 10.0,  
          right: 10.0,  
        ),  
        child: Icon(  
          controller.value.isPlaying  
              ? Icons.pause_rounded  
              : Icons.play_arrow_rounded,  
          color: Colors.white,  
        ),  
      ),  
    );  
  }  
  
  ///播放时间  
  Widget _buildPosition(Color iconColor) {  
    final position = _latestValue != null && _latestValue.position != null  
        ? _latestValue.position  
        : Duration.zero;  
    final duration = _latestValue != null && _latestValue.duration != null  
        ? _latestValue.duration  
        : Duration.zero;  
  
    return Padding(  
      padding: EdgeInsets.only(right: 5.0),  
      child: Text(  
        '${formatDuration(position)}/${formatDuration(duration)}',  
        style: TextStyle(fontSize: 10, color: Colors.white),  
      ),  
    );  
  }  
  
  void _cancelAndRestartTimer() {  
    _hideTimer?.cancel();  
    _startHideTimer();  
  
    setState(() {  
      _hideStuff = false;  
      _displayTapped = true;  
    });  
  }  
  
  Future<void> _initialize() async {  
    controller.addListener(_updateState);  
  
    _updateState();  
  
    if ((controller.value != null && controller.value.isPlaying) ||  
        chewieController.autoPlay) {  
      _startHideTimer();  
    }  
  
    if (chewieController.showControlsOnInitialize) {  
      _initTimer = Timer(const Duration(milliseconds: 200), () {  
        setState(() {  
          _hideStuff = false;  
        });  
      });  
    }  
  }  
  
  void _onExpandCollapse() {  
    setState(() {  
      _hideStuff = true;  
  
      chewieController.toggleFullScreen();  
      _showAfterExpandCollapseTimer =  
          Timer(const Duration(milliseconds: 300), () {  
            setState(() {  
              _cancelAndRestartTimer();  
            });  
          });  
    });  
  }  
  
  void _playPause() {  
    bool isFinished;  
    if (_latestValue.duration != null) {  
      isFinished = _latestValue.position >= _latestValue.duration;  
    } else {  
      isFinished = false;  
    }  
  
    setState(() {  
      if (controller.value.isPlaying) {  
        playPauseIconAnimationController.reverse();  
        _hideStuff = false;  
        _hideTimer?.cancel();  
        controller.pause();  
      } else {  
        _cancelAndRestartTimer();  
  
        if (!controller.value.isInitialized) {  
          controller.initialize().then((_) {  
            controller.play();  
            playPauseIconAnimationController.forward();  
          });  
        } else {  
          if (isFinished) {  
            controller.seekTo(const Duration());  
          }  
          playPauseIconAnimationController.forward();  
          controller.play();  
        }  
      }  
    });  
  }  
  
  void _startHideTimer() {  
    _hideTimer = Timer(const Duration(seconds: 3), () {  
      setState(() {  
        _hideStuff = true;  
      });  
    });  
  }  
  
  void _updateState() {  
    setState(() {  
      _latestValue = controller.value;  
    });  
  }  
  ///进度条  
  Widget _buildProgressBar() {  
    return Expanded(  
      child: Padding(  
        padding: EdgeInsets.only(right: 15,left: 15),  
        child: MaterialVideoProgressBar(  
          controller,  
          onDragStart: () {  
            setState(() {  
              _dragging = true;  
            });  
  
            _hideTimer?.cancel();  
          },  
          onDragEnd: () {  
            setState(() {  
              _dragging = false;  
            });  
  
            _startHideTimer();  
          },  
          colors: chewieController.materialProgressColors ??  
              ChewieProgressColors(  
                  playedColor: Theme.of(context).accentColor,  
                  handleColor: Theme.of(context).accentColor,  
                  bufferedColor: Theme.of(context).backgroundColor,  
                  backgroundColor: Theme.of(context).disabledColor),  
        ),  
      ),  
    );  
  }  
  
  ///中间进度条  
  _loadingIndicator() {  
    //初始化时是否显示loading  
    return widget.showLoadingOnInitialize ? CircularProgressIndicator() : null;  
  }  
  
  ///浮层  
  _overlayUI() {  
    return widget.overlayUI != null  
        ? AnimatedOpacity(  
        opacity: _hideStuff ? 0.0 : 1.0,  
        duration: Duration(milliseconds: 300),  
        child: widget.overlayUI)  
        : Container();  
  }  
}  
  
class _PlaybackSpeedDialog extends StatelessWidget {  
  const _PlaybackSpeedDialog({  
    Key key,  
    @required List<double> speeds,  
    @required double selected,  
  })  : _speeds = speeds,  
        _selected = selected,  
        super(key: key);  
  
  final List<double> _speeds;  
  final double _selected;  
  
  @override  
  Widget build(BuildContext context) {  
    final Color selectedColor = Theme.of(context).primaryColor;  
  
    return ListView.builder(  
      shrinkWrap: true,  
      physics: const ScrollPhysics(),  
      itemBuilder: (context, index) {  
        final _speed = _speeds[index];  
        return ListTile(  
          dense: true,  
          title: Row(  
            children: [  
              if (_speed == _selected)  
                Icon(  
                  Icons.check,  
                  size: 20.0,  
                  color: selectedColor,  
                )  
              else  
                Container(width: 20.0),  
              const SizedBox(width: 16.0),  
              Text(_speed.toString()),  
            ],  
          ),  
          selected: _speed == _selected,  
          onTap: () {  
            Navigator.of(context).pop(_speed);  
          },  
        );  
      },  
      itemCount: _speeds.length,  
    );  
  }  
}  
